package card

import (
	"context"
	"fmt"
	"hotgo/internal/consts"
	"hotgo/internal/dao"
	"hotgo/internal/library/contexts"
	"hotgo/internal/library/hgorm/handler"
	"hotgo/internal/model/entity"
	"hotgo/internal/model/input/adminin"
	"hotgo/internal/model/input/apiin"
	"hotgo/internal/model/input/cardin"
	"hotgo/internal/model/input/sysin"
	"hotgo/internal/service"
	"hotgo/utility/charset"
	"hotgo/utility/convert"
	"hotgo/utility/encrypt"
	"hotgo/utility/tree"
	"time"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/golang-module/dongle"
)

type sCard struct{}

func NewSCard() *sCard {
	return &sCard{}
}

func init() {
	service.RegisterCard(NewSCard())
}

func (s *sCard) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
	return handler.Model(dao.UsersInviteCard.Ctx(ctx), option...)
}

func (s *sCard) ActiveCard(ctx context.Context, in *cardin.CardActiveInp) (res *cardin.CardActiveModel, err error) {
	res = new(cardin.CardActiveModel)
	mod := s.Model(ctx)
	mod = mod.Where(dao.UsersInviteCard.Columns().CardCode, in.CardCode)
	var card entity.UsersInviteCard
	if err = mod.Scan(&card); err != nil {
		err = gerror.NewCode(gcode.CodeInvalidRequest, "激活码无效")
		return
	}
	if card.Status {
		err = gerror.NewCode(gcode.CodeInvalidRequest, "激活码已被使用")
		return
	}

	// 判断卡片状态是否开启
	if !card.Enabled {
		err = gerror.NewCode(gcode.CodeInvalidRequest, "激活码已冻结")
		return
	}

	// 判断卡有效期
	if card.ActivationDeadline != nil {
		if card.ActivationDeadline.Before(gtime.Now()) {
			err = gerror.NewCode(gcode.CodeInvalidRequest, "激活码已过期")
			return
		}
	}

	tx, _ := g.DB().Begin(ctx)
	defer func() {
		if err != nil {
			tx.Rollback()
			return
		}
		tx.Commit()
	}()
	vipCard, err := service.ApiOperation().GetMemberCardOneByType(ctx, consts.AdminMemberMemberTypeMonth)
	if err != nil {
		glog.Errorf(context.Background(), "获取会员卡失败: %s", err.Error())
		err = gerror.NewCode(gcode.CodeInternalError, "获取会员卡失败")
		return
	}

	res.CanUse = true
	// 创建一条订单记录
	orderId, err := service.SysUserOrder().CreateFinishOrderHistory(ctx, &sysin.UserOrderEditInp{
		Order: entity.Order{
			OrderType:    consts.OrderTypeMemberOrder,
			Status:       consts.UserOrderStatusDone,
			MemberCardId: int64(vipCard.Id),
			ProductId:    0,
			Qty:          1,
			PayTime:      gtime.Now(),
			ConfirmTime:  gtime.Now(),
			EndTime:      gtime.Now(),
			ArchiveTime:  gtime.Now(),
			UserId:       contexts.GetUserId(ctx),
			PayMethod:    consts.PayTypeCardActive,
		},
	})
	if err != nil {
		glog.Errorf(context.Background(), "创建订单失败: %s", err.Error())
		err = gerror.NewCode(gcode.CodeInternalError, "创建订单失败")
		return
	}

	if err = service.AdminMember().OpenMember(ctx, &adminin.OpenMemberInp{
		CardId:   int64(vipCard.Id),
		OrderID:  orderId,
		MemberId: contexts.GetUserId(ctx),
	}); err != nil {
		glog.Errorf(context.Background(), "开通会员失败: %s", err.Error())
		err = gerror.NewCode(gcode.CodeInternalError, "开通会员失败")
		return
	}

	// 绑定销氪
	user, err := service.AdminMember().GetById(ctx, &adminin.GetByIdInp{
		Id: contexts.GetUserId(ctx),
	})
	if err != nil {
		glog.Errorf(ctx, "获取用户信息失败: %s", err.Error())
	} else if user.Source == consts.AdminMemberSourceNaturalRegister && user.Pid == 0 {
		xiaoke := new(entity.AdminMember)
		err = service.AdminMember().Model(ctx).
			//Where(dao.AdminMember.Columns().RoleId, consts.RoleXiaoke).
			Wheref(dao.AdminMember.Columns().OldId+" = ? or "+dao.AdminMember.Columns().Id+" = ?",
				card.ParentUid,
				card.ParentUid).
			Scan(xiaoke)
		if err != nil {
			glog.Errorf(ctx, "获取销客信息失败: %s", err.Error())
		} else if xiaoke.Id != 0 {
			_, err = service.AdminMember().Model(ctx).Data(g.Map{
				dao.AdminMember.Columns().Source: consts.AdminMemberSourceOfflineActivation,
				dao.AdminMember.Columns().Pid:    xiaoke.Id,
				dao.AdminMember.Columns().Tree:   tree.GenLabel(xiaoke.Tree, xiaoke.Id),
				dao.AdminMember.Columns().Level:  xiaoke.Level + 1,
			}).Where(dao.AdminMember.Columns().Id, contexts.GetUserId(ctx)).Update()
			if err != nil {
				glog.Errorf(ctx, "绑定销客失败: %s", err.Error())
			}
		}
	}

	// 更新卡片状态
	_, err = s.Model(ctx).Data(g.Map{
		dao.UsersInviteCard.Columns().Status:     true,
		dao.UsersInviteCard.Columns().Uid:        contexts.GetUserId(ctx),
		dao.UsersInviteCard.Columns().ActiveTime: gtime.Now(),
	}).Where(dao.UsersInviteCard.Columns().Id, card.Id).Update()
	if err != nil {
		glog.Errorf(context.Background(), "更新卡片状态失败: %s", err.Error())
		err = gerror.NewCode(gcode.CodeInternalError, "更新卡片状态失败")
		return
	}
	return
}

func (s *sCard) CardInfoByQrCode(ctx context.Context, in *cardin.CardInfoInp) (res *cardin.CardInfoByQrCodeModel, err error) {
	res = new(cardin.CardInfoByQrCodeModel)
	mod := s.Model(ctx)
	var (
		hint     bool
		cardCode string
	)
	if in.CardCode != "" {
		cardCode = in.CardCode
		hint = true
	}
	if in.AccessKey != "" && in.SecretKey != "" {
		cipher := encrypt.GetAesCipher()
		spliceKey := fmt.Sprintf("%s-%s", in.AccessKey, in.SecretKey)
		encryptObj := dongle.Encrypt.FromString(spliceKey).ByAes(cipher)
		cardCode = encryptObj.ToHexString()
		hint = true
	}
	if !hint {
		err = gerror.NewCode(gcode.CodeInvalidRequest, "参数错误")
		return
	}
	var card entity.UsersInviteCard
	mod = mod.Where(dao.UsersInviteCard.Columns().CardCode, cardCode)
	err = mod.Scan(&card)
	if err != nil {
		err = gerror.NewCode(gcode.CodeInvalidRequest, "无法查询到卡片信息")
		return
	}
	res.CardCode = card.CardCode
	res.IsActivate = card.Status

	res.ExpireTime = convert.TimestampToString(card.ActivationDeadline.Unix())
	if card.Status {
		// 这是该功能修改时间，这个时间之后卡片数据库里存的都都是新用户 id，需要去查询 AdminMember的表
		if card.ActiveTime.After(gtime.NewFromStrLayout("2025-03-10 00:00:00", time.DateTime)) {
			newUser, err := service.AdminMember().GetById(ctx, &adminin.GetByIdInp{
				Id: card.Uid,
			})
			if err != nil {
				err = gerror.NewCode(gcode.CodeInternalError, "获取用户信息失败")
				return res, err
			}
			res.ActiveName = newUser.RealName
			res.ActiveUserAvatar = newUser.Avatar
			res.Phone = charset.DesensitizePhoneNum(newUser.Mobile)
		} else {
			//在这个时间之前的去查老用户表
			var oldUser entity.Users
			if err = g.DB(dao.Users.Group()).Model(dao.Users.Table()).Where(dao.Users.Columns().Uid, card.Uid).Scan(&oldUser); err != nil {
				err = gerror.NewCode(gcode.CodeInternalError, "获取用户信息失败")
				return
			}
			res.ActiveName = oldUser.NickName
			res.ActiveUserAvatar = oldUser.Avatar
			res.Phone = charset.DesensitizePhoneNum(oldUser.Phone)
		}
		res.ActiveTime = convert.TimestampToString(card.ActiveTime.Unix())
	}
	if card.ActivationDeadline != nil {
		if card.ActivationDeadline.Before(gtime.Now()) {
			res.Expired = true
		}
	}
	res.Enable = card.Enabled
	if card.Enabled && !card.Status && !res.Expired {
		res.Available = true
	}
	return
}

// 赠送会员
func (s *sCard) giftVIP(ctx context.Context, vipCardID int64) (err error) {
	memberId := contexts.GetUserId(ctx)

	member, err := service.AdminMember().View(ctx, &adminin.MemberViewInp{
		Id: memberId,
	})
	if err != nil {
		return err
	}

	vipCardDetail, err := service.ApiOperation().MemberCardDetail(ctx, &apiin.MemberCardDetailInp{
		Id: vipCardID,
	})
	if err != nil {
		return err
	}

	// 会员过期时间
	var expireTime *gtime.Time
	if member.ExpireTime != nil && member.ExpireTime.After(gtime.Now()) {
		expireTime = member.ExpireTime.AddDate(0, 0, vipCardDetail.MemberDays+vipCardDetail.ExtraDays)
	} else {
		expireTime = gtime.Now().AddDate(0, 0, vipCardDetail.MemberDays+vipCardDetail.ExtraDays)
	}

	// 更新会员信息
	err = service.AdminMember().UpdateInfo(ctx, &adminin.MemberUpdateInfoInp{
		ID:           member.Id,
		MemberStatus: consts.AdminMemberMemberStatusMember,
		MemberType:   vipCardDetail.CardType,
		ExpireTime:   expireTime,
	})
	if err != nil {
		glog.Errorf(context.Background(), "修改用户信息失败: %s", err.Error())
		return
	}

	// 订单设置会员过期时间 end_time
	//_, err = g.DB().Model(dao.Order.Table()).Data("end_time", expireTime).WherePri(orderID).Update()
	//if err != nil {
	//	glog.Errorf(context.Background(), "更新订单过期时间失败")
	//	return
	//}
	return
}
